/**
 * 
 */
package com.feib.stms.security.captcha;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.util.Assert;
import org.springframework.web.filter.GenericFilterBean;

/**
 * @title (#)StpsSecurityCaptchaFilter.java<br>
 * @description 畫面上圖形辨識檢核.<br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/12/20 create by Jimmy Liu<br>
 */
public class StmsSecurityCaptchaFilter extends GenericFilterBean {
	
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();

//    private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
    
	private String filterProcessesUrl = "/stps_security_login";
    
//    private String failureUrl = "/login.jsp?captchaError=true";
	
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
	{
        
		HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        

        //remenber that we need an id to validate!  
        String captchaId = "";
        

        
        if (null != request.getSession(false))
        	captchaId = request.getSession().getId();
        
        if (!requiresAuthentication(request, response) || "".equals(captchaId)) {
            chain.doFilter(request, response);
            return;
        } 
        
        if (logger.isTraceEnabled()) {
            logger.trace("SessionId[{}], 驗證碼開始檢核...", captchaId);
        }
        
        //retrieve the response  
        String responsestr = request.getParameter("j_captcha_response");

        // Call the Service method
        
        Boolean isResponseCorrect = null;
        boolean skip = false;
        try {  
            isResponseCorrect = CaptchaServiceSingleton.getInstance().validateResponseForID(captchaId, responsestr);
            
        } catch (Exception e) {
            logger.warn("驗證碼發生錯誤, 不檢核驗證碼", e);
            skip = true;
            chain.doFilter(request, response);
        }
        
        if (!skip)
        {
	        if(null != isResponseCorrect && isResponseCorrect.booleanValue())
	        {
	            // 到下一個 帳號密碼驗證
	            chain.doFilter(request, response);
	        }
	        else
	        {
	        	AuthenticationException failed = new CaptchaAuthenticationException("驗證碼錯誤");
	        	failureHandler.onAuthenticationFailure(request, response, failed);
	        }
        }
	}
	
	protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        String uri = request.getRequestURI();
        int pathParamIndex = uri.indexOf(';');

        if (pathParamIndex > 0) {
            // strip everything after the first semi-colon
            uri = uri.substring(0, pathParamIndex);
        }

        if ("".equals(request.getContextPath())) {
            return uri.endsWith(filterProcessesUrl);
        }

        return uri.endsWith(request.getContextPath() + filterProcessesUrl);
    }

    
    /**
     * @param filterProcessesUrl the filterProcessesUrl to set
     */
    public void setFilterProcessesUrl(String filterProcessesUrl) {
        this.filterProcessesUrl = filterProcessesUrl;
    }
    
    public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
        Assert.notNull(failureHandler, "failureHandler cannot be null");
        this.failureHandler = failureHandler;
    }

}
